#pragma once

#include "swsession.h"

//////////////////////////////////////////////////////////
// Session Manager
//////////////////////////////////////////////////////////

typedef std::vector<CSession*>	vecSESSION;

class CSessionMgr
{
public:
	CSessionMgr() : m_CS(TRUE), m_SessionPool(DEFAULT_CHUNK_SIZE, NULL, 0, _T("NetEngine::SessionPool") )
	{
	}

	~CSessionMgr()
	{
		Cleanup();
	}

protected:
	CCriticalSectionBS			m_CS;

	CIDPool						m_IDPool;

	CChunkAllocatorST<CSession>	m_SessionPool;
	
	vecSESSION					m_ActiveSessions;

public:
	void	Cleanup()
	{
		CSession* pSession = NULL;
		for (size_t i = 0; i < m_ActiveSessions.size(); ++i)
		{
			pSession = m_ActiveSessions[i];
			if (pSession != NULL)
			{
				pSession->Close(DISCONNECT_REASON_ENGINE_SHUTDOWN);
				pSession->Unlink();
			}
		}
		m_ActiveSessions.clear();
	}

	BOOL	Create(int PoolChunkSize)
	{
		SCOPED_LOCK_SINGLE(&m_CS);

		if (m_IDPool.Create(PoolChunkSize) == FALSE)
			return FALSE;

		m_ActiveSessions.resize(PoolChunkSize);
		std::fill(m_ActiveSessions.begin(), m_ActiveSessions.end(), (CSession*)NULL);
		
		return TRUE;
	}

	long	CloseStaleSessions(DWORD dwTimeout);
	BOOL	FreeSession(CSockStream* pSock);
	BOOL	FreeSession(DWORD dwSession, DWORD dwReason);
	DWORD	CreateNewSession(CSockStream* pNewSock, DWORD dwDefaultTask);
	
	DWORD	GetSessionCount() 
	{ 
		long ActiveSessionCount = 0;
		::InterlockedExchange(&ActiveSessionCount, GET_CLASSLINK_CNT(CSession));
		return ActiveSessionCount;
	}

	CSession*	GetSession(DWORD dwSession) 
	{ 
		SCOPED_LOCK_SINGLE(&m_CS);
		_ASSERT(dwSession <= m_ActiveSessions.size()); 
		return m_ActiveSessions[dwSession]; 
	}
	
	void	InvalidateAllSessions();
	void	GetUsage(size_t& Total, size_t& Used, size_t& Free);
	void	CloseAllPassiveSession();
};





















